package model

import (
	"time"

	"bilinadmin/pkg/db/pgex"

	"bilinadmin/pkg/util"
)

const (
	// 管理实体类型
	RefTypeBrand     int8 = 1
	RefTypeStore     int8 = 2
	RefTypeInventory int8 = 3

	RefTypeBrandStr     string = "brand"
	RefTypeStoreStr     string = "store"
	RefTypeInventoryStr string = "inventory"
)

// EmpRole 员工角色
type EmpRole struct {
	Id int64 `json:"id" sql:"id"`
	// 品牌id
	BrandId int64 `json:"brand_id" sql:"brand_id"`
	// 所属对象id
	RefId int64 `json:"ref_id" sql:"ref_id"`
	// 所属对象类型
	RefType int8 `json:"ref_type" sql:"ref_type"`
	// 角色名
	Name string `json:"name" sql:"name"`
	// 是否是管理员
	IsAdmin bool `json:"is_admin" sql:"is_admin"`
	// 创建人
	ModifyEmpId int64 `json:"modify_emp_id" sql:"modify_emp_id"`
	// 创建时间
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	// 更新时间
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
	// 删除时间
	DeletedAt int64 `json:"deleted_at" sql:"deleted_at"`
}

// GetRefInfoForBrandStore ref_type ref_id 区分
func GetRefInfoForBrandStore(brandId, storeId int64) (int64, int8) {
	if brandId == 0 {
		return 0, 0
	}
	if storeId != 0 {
		return storeId, RefTypeStore
	}
	return brandId, RefTypeBrand
}

// NewEmpRole 员工角色
func NewEmpRole(brandId, refId int64, refType int8, name string, creator int64) *EmpRole {
	now := util.GetNow()
	return &EmpRole{
		BrandId:     brandId,
		RefId:       refId,
		RefType:     refType,
		Name:        name,
		ModifyEmpId: creator,
		CreatedAt:   now,
		UpdatedAt:   now,
	}
}

// Update 更新
func (r *EmpRole) Update(name string, empId int64) {
	if name != "" {
		r.Name = name
	}
	if empId != 0 {
		r.ModifyEmpId = empId
	}
	r.UpdatedAt = util.GetNow()
}

// SetAdmin 设置为管理员
func (r *EmpRole) SetAdmin() {
	r.IsAdmin = true
	r.UpdatedAt = util.GetNow()
}

func GetInnerRefType(ref string) int8 {
	switch ref {
	case RefTypeBrandStr:
		return RefTypeBrand
	case RefTypeStoreStr:
		return RefTypeStore
	case RefTypeInventoryStr:
		return RefTypeInventory
	default:
		return 0
	}
}

// RolePermission 角色权限
type RolePermission struct {
	Id int64 `json:"id" sql:"id"`
	// 角色id
	RoleId int64 `json:"role_id" sql:"role_id"`
	// 主权限id
	PerId int64 `json:"per_id" sql:"per_id"`
	// 子权限列表
	SubPerIds pgex.Int64Array `json:"sub_per_ids" sql:"sub_per_ids"`
	// 创建人
	ModifyEmpId int64 `json:"modify_emp_id" sql:"modify_emp_id"`
	// 创建时间
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	// 更新时间
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
	// 删除时间
	DeletedAt int64 `json:"deleted_at" sql:"deleted_at"`
}

// NewRolePermission 角色权限
func NewRolePermission(roleId, creator int64) *RolePermission {
	now := util.GetNow()
	return &RolePermission{
		RoleId:      roleId,
		SubPerIds:   []int64{},
		ModifyEmpId: creator,
		CreatedAt:   now,
		UpdatedAt:   now,
	}
}

// AddPermission 添加主权限
func (p *RolePermission) AddPermission(perId int64) {
	p.PerId = perId
	p.UpdatedAt = util.GetNow()
}

// AddSubPermission 添加子权限
func (p *RolePermission) AddSubPermission(subPerId int64) {
	p.SubPerIds = append(p.SubPerIds, subPerId)
	p.UpdatedAt = util.GetNow()
}

// RoleAgg 角色
type RoleAgg struct {
	Role   *EmpRole
	PerMap map[int64]*RolePermission
	Perms  []*RolePermission
}

func NewRole(role *EmpRole, perms []*RolePermission) *RoleAgg {
	if role == nil {
		return nil
	}
	perMap := map[int64]*RolePermission{}
	for _, p := range perms {
		perMap[p.PerId] = p
	}
	return &RoleAgg{
		Role:   role,
		PerMap: perMap,
		Perms:  perms,
	}
}

// HasPermission 判断是否有权限
func (r *RoleAgg) HasPermission(perId, subPerId, refId int64, refType int8) bool {
	// 角色归属实体判断
	if r.Role.RefId != refId || r.Role.RefType != refType {
		return false
	}
	// 管理员有所有权限
	if r.Role.IsAdmin {
		return true
	}
	// 权限判断
	per, ok := r.PerMap[perId]
	if !ok {
		return false
	}
	if per == nil {
		return false
	}
	// 判断子权限,为空说明有所有权限
	if len(per.SubPerIds) == 0 {
		return true
	}
	return util.ContainInt64(per.SubPerIds, subPerId)
}
